﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using System.Threading;
using System.Security;

namespace iLangl
{
	public abstract class BaseAction : BaseActionDescriptor, IAction
	{
		#region ISecurityContext Members

		public string SessionId
		{
			get;
			set;
		}

		public string PluginLiceneKey
		{
			get;
			set;
		}

		public string ContactId
		{
			get;
			set;
		}

		public string CompanyId
		{
			get;
			set;
		}

		#endregion

		private ILog _log = null;
		protected ILog log
		{
			get
			{
				if (_log == null)
				{
					_log = LogManager.GetLogger(String.Format("{0} - Version {1} ", GetName(), GetVersion()));
				}
				return _log;
			}
		}

		public virtual int TimeOutInMinutes
		{
			get
			{
				return 60;
			}
		}

		protected void weGetResult()
		{
			finished = true;
		}
		private bool finished = false;
		protected void waitForResult()
		{
			finished = false;
			DateTime start = DateTime.Now;
			while (!finished)
			{
				Thread.Sleep(10);

				if ((DateTime.Now - start).TotalSeconds > TimeOutInMinutes)
				{
					throw new TimeoutException(String.Format("Action with name='{0}' failed to get results!", GetName()));
				}
			}
		}


		public BaseAction()
		{
			actionName = GetName();
			version = GetVersion();
			actionId = GetActionId();
			ResponseContext = new BaseContext();
			RequestContext = new BaseContext();
			
		}

		
		protected abstract String GetName();
		protected abstract String GetVersion();
		protected abstract String GetActionId();

		

		public virtual void SetActionDescriptor(IActionDescriptor descriptor)
		{
			actionId = descriptor.Id;
			version = descriptor.Version;
			actionName = descriptor.ActionName;
			Container = descriptor.Container;
			isSynced = descriptor.IsSynced;
		}

		protected virtual void  actionFinished()
		{
			Facade.Instance.PackageManager.PackageProcessed(Container);
		}

		protected virtual void actionFailed()
		{
			Facade.Instance.PackageManager.PackageCorrupted(Container);
		}

		protected virtual void _execute()
		{
			if (this.Container != null)
				this.Container.AddPackage(preparePackage());	
		}

		protected virtual IPackage preparePackage()
		{
			Facade.Instance.ActionManager.RegisterAction(this);
			IPackage package = Facade.Instance.PackageManager.CreateNewPackage();
			package.AddAction(this);

			return package;
		}

		public virtual void SentRequest(IPackage package)
		{
			
		}

		protected virtual void validate()
		{
		}

		protected virtual void registerException(Exception ex)
		{
			IAlert alert = Facade.Instance.AlertManager.CreateAlert(this);

			alert.AddException(ex);
			alert.AddAction(this);
			alert.AddPackage(this.Container);

			Facade.Instance.AlertManager.RaiseAlert(alert);
		}

		#region IAction Members
		public void Execute()
		{
			try
			{
				DateTime start = DateTime.Now;
				log.DebugFormat(
					" In Progress Action {0} with Id{1}(Version - {2})",
					GetName(),
					GetActionId(),
					GetVersion());

				validate();

				

				_execute();


				log.DebugFormat(
					"Finished Action {0} with Id={1} (Version - {2}). Executed Time in Seconds- {3}",
					GetName(),
					GetActionId(),
					GetVersion(),
					(start - DateTime.Now).TotalSeconds
					);

				actionFinished();
			}
			catch (Exception ex)
			{
				actionFailed();
				try
				{

					log.Error(

						string.Format("Error in action {0} with Id{1}(Version - {2},Context - {3})",
						GetName(),
						GetActionId(),
						GetVersion(),
						(this.ResponseContext.GetContext() == null) ? string.Empty : this.ResponseContext.GetContext().ToString()),
						ex);

					throw ex;
				}
				catch (Exception ex1)
				{
					log.Fatal(ex1);
					throw ex1;
				}
			}
		}


		public virtual void Send()
		{
			if(Container == null)
			{
				Container = preparePackage();
			}


			Facade.Instance.CommunicationManager.SentPackage(Container);
		}
		#endregion
	}
}
